package cn.com.dhcc.turbo.service.monitor.gather;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.tag.CommonStaticCode.YESNO;
import cn.com.dhcc.app.core.util.CollectionUtil;
import cn.com.dhcc.app.core.util.FreemarkerUtil;
import cn.com.dhcc.app.core.util.JsUtil;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.turbo.entity.monitor.QuotaValueOnTime;
import cn.com.dhcc.turbo.entity.registry.DomainInfo;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.service.monitor.MonitorService;
import cn.com.dhcc.turbo.service.monitor.QUOTA;
import cn.com.dhcc.turbo.service.registry.DomainInfoService;
import cn.com.dhcc.turbo.service.registry.NodeInfoService;

@Service
public class QuotaGatherUtil {

	@Autowired
	MonitorService monitorService;
	@Autowired
	NodeInfoService nodeInfoService;
	@Autowired
	DomainInfoService domainInfoService;
	@SuppressWarnings("deprecation")
	static Logger logger = Log.getExistLogger(LOGTYPE.MONITOR);
	private static final String QUOTA_FOR_ADAPTER_SUFFIX = "_FOR_ADAPTER";
	private static final String QUOTA_FOR_DOMAIN_SUFFIX = "_FOR_DOMAIN";
	private static final String QUOTA_FOR_NODE_SUFFIX = "_FOR_NODE";
	
	
	/**
	 * 通用方法（可重新）：根据系统指标最新值计算节点的指标值
	 * 计算规则：
	 * 节点指标值=sum(系统指标值) 
	 * @param sysQuotaCodes 需要进行计算的系统指标编码（可多个）
	 * @throws ServiceException 
	 */
	public void gatherValueForNodeByAdapterLastValue(QUOTA[] adapterQuotas) throws ServiceException{
		if(adapterQuotas!=null&&adapterQuotas.length!=0){
			Date now = new Date();
			NodeInfo localNode = nodeInfoService.getLocalNode();
			for (int i = 0; i < adapterQuotas.length; i++) {
				QUOTA adapterQuota = adapterQuotas[i];
				String adapterQuotaCode = adapterQuota.getCode();
				QUOTA quotaForNode = getNodeQuotaCodeBySysQuotaCode(adapterQuotaCode.toUpperCase());
				String quotaCodeForNode = quotaForNode.getCode();
				//获取这个指标的最新的值，然后做计算
				String forNode_v1 = "0";
				String forNode_v2 = "0";
				List<QuotaValueOnTime> quotaValueOnTimes =	monitorService.getLastQuotaValueByQuotaCode(adapterQuotaCode);
				if(CollectionUtil.hasElement(quotaValueOnTimes)){
					logger.info("开始自动根据适配器指标["+adapterQuotaCode+"]值计算节点指标指标["+quotaCodeForNode+"]...");
					for (Iterator<QuotaValueOnTime> iterator = quotaValueOnTimes.iterator(); iterator
							.hasNext();) {
						QuotaValueOnTime quotaValueOnTime = iterator.next();
						String sv1 = quotaValueOnTime.getCurrentValue1();
						String sv2 = quotaValueOnTime.getCurrentValue2();
						try {
							forNode_v1 = plus(forNode_v1, sv1);
							if(StringUtils.hasText(sv2)){
								forNode_v2 =plus(forNode_v2, sv2); 
							}
						} catch (Exception e) {
							logger.error("自动根据系统指标["+adapterQuotaCode+"]值计算节点指标指标["+quotaCodeForNode+"]失败",e);
							break;//跳出对当前指标的计算
						} 
					}
				}
				//插入节点指标值
				try {
					QuotaValueOnTime onTime = new QuotaValueOnTime();
					onTime.setCanMerge(YESNO.YES.getStatus());
					onTime.setCurrentValue1(forNode_v1);
					onTime.setCurrentValue2(forNode_v2);
					onTime.setId(UUIDGenerator.getUUID());
					onTime.setMtime(now);
					onTime.setQuotaCode(quotaCodeForNode);
					onTime.setOwnerId(localNode.getId());
					monitorService.insertOrUpdateQuotaOnTime(onTime);
					logger.info("自动根据系统指标["+adapterQuotaCode+"]值计算节点指标指标["+quotaCodeForNode+"]成功,值1:"+forNode_v1+",值2:"+forNode_v2);
				} catch (Exception e) {
					logger.error("自动根据系统指标["+adapterQuotaCode+"]值计算节点指标指标["+quotaCodeForNode+"]失败,值1:"+forNode_v1+",值2:"+forNode_v2,e);
				}
			}
		}
	}
	
	/**
	 * 通用方法（可重新）：根据系统指标最新值计算域的指标值
	 * 计算规则：
	 * 域指标值=sum(域包含系统的指标)
	 * @param sysQuotaCodes 需要进行计算的系统指标编码（可多个）
	 * @throws ServiceException 
	 */
	public void gatherValueForDomainByAdapterLastValue(QUOTA[] sysQuotas) throws ServiceException{
		if(sysQuotas!=null&&sysQuotas.length!=0){
			Date now = new Date();
			List<DomainInfo> domainInfos = domainInfoService.list(null);
			if(!CollectionUtil.hasElement(domainInfos)){
				return;
			}
			for (Iterator<DomainInfo> iterator = domainInfos.iterator(); iterator.hasNext();) {
				DomainInfo domainInfo =  iterator.next();
				String domainId = domainInfo.getId();
				for (int i = 0; i < sysQuotas.length; i++) {
					QUOTA sysQuota = sysQuotas[i];
					String sysQuotaCode = sysQuota.getCode();
					QUOTA quotaForDomain = getDomainQuotaCodeBySysQuotaCode(sysQuotaCode.toUpperCase());
					String quotaCodeForDomain = quotaForDomain.getCode();
					//获取这个指标的最新的值，然后做计算
					String forDomain_v1 = "0";
					String forDomain_v2 = "0";
					List<QuotaValueOnTime> quotaValueOnTimes =	monitorService.getLastSysQuotaValueByDomainId(domainId,sysQuotaCode);
					if(CollectionUtil.hasElement(quotaValueOnTimes)){
						logger.info("开始自动根据系统指标["+sysQuotaCode+"]值计算域指标指标["+quotaCodeForDomain+"]...");
						for (Iterator<QuotaValueOnTime> iterator2 = quotaValueOnTimes.iterator(); iterator2
								.hasNext();) {
							QuotaValueOnTime quotaValueOnTime = iterator2.next();
							String sv1 = quotaValueOnTime.getCurrentValue1();
							String sv2 = quotaValueOnTime.getCurrentValue2();
							try {
								forDomain_v1 = plus(forDomain_v1, sv1);
								if(StringUtils.hasText(sv2)){
									forDomain_v2 =plus(forDomain_v2, sv2); 
								}
							} catch (Exception e) {
								logger.error("自动根据系统指标["+sysQuotaCode+"]值计算域指标指标["+quotaCodeForDomain+"]失败",e);
								break;//跳出对当前指标的计算
							}
						}
					}
					//插入节点指标值
					try {
						QuotaValueOnTime onTime = new QuotaValueOnTime();
						onTime.setCanMerge(YESNO.YES.getStatus());
						onTime.setCurrentValue1(forDomain_v1);
						onTime.setCurrentValue2(forDomain_v2);
						onTime.setId(UUIDGenerator.getUUID());
						onTime.setMtime(now);
						onTime.setQuotaCode(quotaCodeForDomain);
						onTime.setOwnerId(domainId);
						monitorService.insertOrUpdateQuotaOnTime(onTime);
						logger.info("自动根据系统指标["+sysQuotaCode+"]值计算域指标指标["+quotaCodeForDomain+"]成功,值:"+forDomain_v1+","+forDomain_v2);
					} catch (Exception e) {
						logger.error("自动根据系统指标["+sysQuotaCode+"]值计算域指标指标["+quotaCodeForDomain+"]失败,值:"+forDomain_v1+","+forDomain_v2,e);
					}
				}
			}
		}
	}
	/**
	 * 根据系统指标名得到节点指标名，系统指标名必须以_SYS结尾，得到的节点指标名以_NODE结尾，例如：
	 * STRUCTURED_SEND_FAIL_NUM_FOR_SYS -> STRUCTURED_SEND_FAIL_NUM_FOR_NODE
	 * @param sysQuotaCode 
	 * @return
	 */
	public static QUOTA getNodeQuotaCodeBySysQuotaCode(String sysQuotaCode){
		if(!sysQuotaCode.endsWith(QUOTA_FOR_ADAPTER_SUFFIX)){
			throw new RuntimeException("系统指标必须以[_SYS]结尾");
		}
		String quotaCodeForNode = sysQuotaCode.substring(0, sysQuotaCode.length()-QUOTA_FOR_ADAPTER_SUFFIX.length())+QUOTA_FOR_NODE_SUFFIX;
		QUOTA quotaCode = QUOTA.valueOf(quotaCodeForNode);
		if(quotaCode==null){
			throw new RuntimeException("根据系统指标名["+sysQuotaCode+"]得到对应的节点指标名["+quotaCodeForNode+"]不存在");
		}
		logger.info("根据系统指标名["+sysQuotaCode+"]得到对应的节点指标名["+quotaCodeForNode+"]");
		return quotaCode;
	}
	/**
	 * 根据系统指标名得到域指标名，系统指标名必须以_SYS结尾，得到的域指标名以_DOMAIN结尾，例如：
	 * STRUCTURED_SEND_FAIL_NUM_FOR_SYS -> STRUCTURED_SEND_FAIL_NUM_FOR_DOMAIN
	 * @param sysQuotaCode 
	 * @return
	 */
	public static QUOTA getDomainQuotaCodeBySysQuotaCode(String sysQuotaCode){
		if(!sysQuotaCode.endsWith(QUOTA_FOR_ADAPTER_SUFFIX)){
			throw new RuntimeException("系统指标必须以[_SYS]结尾");
		}
		String quotaCodeForDomain = sysQuotaCode.substring(0, sysQuotaCode.length()-QUOTA_FOR_ADAPTER_SUFFIX.length())+QUOTA_FOR_DOMAIN_SUFFIX;
		QUOTA quotaCode = QUOTA.valueOf(quotaCodeForDomain);
		if(quotaCode==null){
			throw new RuntimeException("根据系统指标名["+sysQuotaCode+"]得到对应的域指标名["+quotaCodeForDomain+"]不存在");
		}
		logger.info("根据系统指标名["+sysQuotaCode+"]得到对应的域指标名["+quotaCodeForDomain+"]");
		return quotaCode;
	}
	private String plus(String v1,String v2) throws Exception{
		Map<String, String> rootMap = new HashMap<String, String>();
		rootMap.put("v1", v1);
		rootMap.put("v2", v2);
		String express = FreemarkerUtil.flushStringTemplateData("${v1}+${v2}",rootMap);
		Object reslt = JsUtil.simpleComputeExpress(express);
		if(reslt instanceof Double){
			return String.valueOf(((Double)JsUtil.simpleComputeExpress(express)).intValue());
		}else{
			return String.valueOf(((Integer)JsUtil.simpleComputeExpress(express)).intValue());
		}
		
	}
}
